package com.eascs.web.o2o.quartz.util;

import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.scheduler.common.entity.ScheduleJob;
import com.eascs.web.o2o.quartz.service.BaseJobService;

@Component
public class QuartzManager implements BeanFactoryAware {

	private Logger log = LoggerFactory.getLogger(QuartzManager.class);
	
	private static BeanFactory beanFactory = null;

	@Autowired
    SchedulerFactoryBean schedulerFactoryBean;

	/*private static Scheduler scheduler;*/
	
	@Inject
	BaseJobService baseJobService;

	private static boolean flag = true;// 开关
	
	
	/*static{
		scheduler = schedulerFactoryBean.getScheduler();
	}*/

	public void reScheduleJob() throws Exception {
		if (flag == true) {
			// 通过查询数据库里计划任务来配置计划任务
			List<ScheduleJob> quartzList = baseJobService.getJobList();
			if (quartzList != null && quartzList.size() > 0) {
				for (ScheduleJob job : quartzList) {
					configQuatrz(job);
				}
			}
		}
		flag = false;
	}

	public void configQuatrz(ScheduleJob job) {
		try {
			Scheduler scheduler = null;
			if (schedulerFactoryBean != null && scheduler == null) {
				scheduler = schedulerFactoryBean.getScheduler();
			}
			// 运行时可通过动态注入的scheduler得到trigger
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getTriggerName(), Scheduler.DEFAULT_GROUP);
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			// 如果计划任务已存在则调用修改方法(触发器是任务调度中的最小单位)
			if (trigger != null) {
				change(job, scheduler);
			} else {
				// 如果计划任务不存在并且数据库里的任务状态为可用时,则创建计划任务
				if (job.getJobStatus().equals("1")) {
					createCronTriggerBean(job, scheduler);
				}
			}
			if(!scheduler.isShutdown()){
				scheduler.start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void change(ScheduleJob job, Scheduler scheduler) throws Exception {
		TriggerKey triggerKey = TriggerKey.triggerKey(job.getTriggerName(), Scheduler.DEFAULT_GROUP);
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		// 如果任务为可用
		if (job.getJobStatus().equals("1")) {
			// 判断从DB中取得的任务时间和现在的quartz线程中的任务时间是否相等
			// 如果相等，则表示用户并没有重新设定数据库中的任务时间，这种情况不需要重新rescheduleJob
			if (!trigger.getCronExpression().equalsIgnoreCase(job.getCronExpression())) {
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
				trigger = TriggerBuilder.newTrigger().withIdentity(job.getTriggerName(), scheduler.DEFAULT_GROUP)
						.withSchedule(scheduleBuilder).build();
				scheduler.rescheduleJob(triggerKey, trigger);//重新设置触发器，到设定的时间，便开始执行任务
				log.info(new Date() + ": 更新" + job.getTriggerName() + "计划任务");
			}
		} else {
			// 不可用
			scheduler.pauseTrigger(triggerKey);// 停止触发器
			log.info(new Date() + ": 删除" + job.getTriggerName() + "计划任务");

		}

	}

	/**
	 * 创建/添加计划任务
	 * 
	 * @param tbcq
	 *            计划任务配置对象
	 * @throws Exception
	 */
	public void createCronTriggerBean(ScheduleJob job, Scheduler scheduler) throws Exception {
		// 1.新建一个基于Spring的管理Job类
		MethodInvokingJobDetailFactoryBean mjdfb = new MethodInvokingJobDetailFactoryBean();
		mjdfb.setName(job.getJobName());// 设置Job名称
		mjdfb.setGroup(Scheduler.DEFAULT_GROUP);
		// 如果定义的任务类为Spring的定义的Bean则调用 getBean方法
		if (job.getIsSpringbean().equals("1")) {
			mjdfb.setTargetObject(beanFactory.getBean(job.getClassPath()));// 设置任务类
		} else {// 否则直接new对象
			mjdfb.setTargetObject(Class.forName(job.getClassPath()).newInstance());// 设置任务类
		}
		mjdfb.setTargetMethod(job.getMethod());// 设置任务方法
		mjdfb.setConcurrent(job.getConcurrent().equals("0") ? false : true); // 设置是否并发启动任务（若是并发执行，就会出现一个任务上次还未执行完 ，下次就开始执行了）
		mjdfb.afterPropertiesSet();// 将管理Job类提交到计划管理类
		// 2.将Spring的管理Job类转为Quartz管理Job类
		JobDetail jobDetail = mjdfb.getObject();
		jobDetail.getJobDataMap().put("scheduleJobInfo", job);
		//scheduler.addJob(jobDetail, true); // 将Job添加到管理类（此处若设置会导致重复注册）
		//3.创建一个触发器
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getTriggerName(), Scheduler.DEFAULT_GROUP)
				.withSchedule(scheduleBuilder).build();
		//4.将job和触发器交由调度器管理
		scheduler.scheduleJob(jobDetail, trigger);
	}

	public void setBeanFactory(BeanFactory factory) throws BeansException {
		this.beanFactory = factory;

	}

	public BeanFactory getBeanFactory() {
		return beanFactory;
	}
}